﻿using System.Collections.Generic;
using System.Text;
using ibba.agil.core.Internal;
using System.Data.SqlClient;
using System.Data;
using System.Reflection;
using System;
using ibba.agil.core.common;

namespace ibba.agil.core
{
    public abstract class EntityManager<T> where T : ibba.agil.core.EntityData
    {
        public abstract void Save(T entityDataObject);

        public abstract void Save(T entityDataObject, TransactionManager transaction);

        public abstract void Delete(T entityDataObject);

        /// <summary>
        /// Responsavel por realizar a percistencia do objeto na entidade
        /// Para esta sobre carga estaremos assumindo o auto-commit
        /// </summary>
        /// <param name="entityDataObject">Entidade Percistente</param>
        protected void SaveEntity(T entityDataObject)
        {
            using (TransactionManager tm = new TransactionManager(entityDataObject.GetType().Name))
            {
                SaveEntity(entityDataObject, tm);
            }
        }

        /// <summary>
        /// Responsavel por realizar a percistencia do objeto na entidade
        /// </summary>
        /// <param name="entityDataObject">Entidade Percistente</param>
        protected void SaveEntity(T entityDataObject, TransactionManager tm)
        {
            var cmmSql = string.Empty;
            Int16 cp = 1;
            try
            {
                cmmSql
                    = (State(entityDataObject, tm) == EntityState.Materialized) ?
                                EntitySqlLanguage.Update(entityDataObject) :
                                EntitySqlLanguage.Insert(entityDataObject);
                var sqlCommand
                    = new SqlCommand(cmmSql, tm.Connection);
                cp = 2;
                sqlCommand.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                tm.Dispose();
                throw new DASException("SaveEntity", cp, e.Message, cmmSql, e);
            }
        }

        protected void DeleteEntity(T entityDataObject)
        {
            using (TransactionManager tm = new TransactionManager(entityDataObject.GetType().Name))
            {
                DeleteEntity(entityDataObject, tm);
            }
        }

        private EntityState State(T entityDataObject, TransactionManager tm)
        {
            var _sql = EntitySqlLanguage.SelectExist(entityDataObject);
            EntityState _st = EntityState.Created;


            var errorContext = "Query Command " + _sql + "\n";
            
                SqlCommand sqlCommand
                   = new SqlCommand(_sql, tm.Connection);

                 var count = (int)sqlCommand.ExecuteScalar();

                 _st = count > 0 ? EntityState.Materialized : EntityState.Created;
            
            
            return _st;
        }


        protected void DeleteEntity(T entityDataObject, TransactionManager tm)
        {
            var cmmSql = string.Empty;
            Int16 cp = 1;
            try
            {
                cmmSql = EntitySqlLanguage.Delete(entityDataObject);
                var sqlCommand
                    = new SqlCommand(cmmSql, tm.Connection);
                cp = 2;
                sqlCommand.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                tm.Dispose();
                throw new DASException("DeleteEntity", cp, ex.Message, cmmSql, ex);
            }

        }
    }
}
